6364ef2fe0ad6ca68c4b529d4a6eae1f3848c59c,src/main/java/org/datanucleus/metadata/ClassMetaData.java,ClassMetaData,addMetaDataForMembersNotInMetaData,#Class#,350
Before Change
{
// User has class declaration like "public class MyClass<T extends SomeType>" so take SomeType
boolean overrideIfNotPresent = true;
AbstractMemberMetaData overriddenMmd = getMetaDataForMember(ClassUtils.getFieldNameForJavaBeanGetter(allclsMethods[i].getName()));
if (overriddenMmd != null)
{
if (!overriddenMmd.getTypeName().equals(((Class)boundTypes[0]).getName()))
{
// Already overridden the type in a superclass, so ignore
overrideIfNotPresent = false;
}
}
// TODO Maybe should use just the declTypes for this specific class?
if (overrideIfNotPresent)
{
NucleusLogger.METADATA.debug("Class=" + cls.getName() + " property=" + allclsMethods[i].getName() +
" declared to be " + methodTypeVar + ", namely TypeVariable(" + j + ") with bound, so using bound of " + boundTypes[0]);
String propertyName = allclsMethods[i].getDeclaringClass().getName() + "." + ClassUtils.getFieldNameForJavaBeanGetter(allclsMethods[i].getName());
if (!memberNames.contains(propertyName))
{
// No property of this name - add a default PropertyMetaData for this method with the type set to what we need
NucleusLogger.METADATA.debug(Localiser.msg("044060", fullName, propertyName));
// TODO Use MetaDataMerger to merge with the overridden
AbstractMemberMetaData mmd = new PropertyMetaData(this, propertyName);
mmd.type = (Class) boundTypes[0];
members.add(mmd);
memberNames.add(mmd.getName());
Collections.sort(members);
foundTypeForTypeVariable = true;
}
}
}
}
}
}
}
}
}
else
{
// Check for any TypeVariables used with fields in superclass(es) and override the metadata in the superclass to use the right type
Class theClass = cls;
while (theClass.getSuperclass() != null)
{
theClass = theClass.getSuperclass();
Field[] theclsFields = theClass.getDeclaredFields();
for (int i=0;i<theclsFields.length;i++)
{
if (!ClassUtils.isInnerClass(theclsFields[i].getName()) && !Modifier.isStatic(theclsFields[i].getModifiers()) &&
!mmgr.isEnhancerField(theclsFields[i].getName()) &&
theclsFields[i].getGenericType() != null && theclsFields[i].getGenericType() instanceof TypeVariable)
{
TypeVariable fieldTypeVar = (TypeVariable) theclsFields[i].getGenericType();
Class declCls = theclsFields[i].getDeclaringClass();
TypeVariable[] declTypes = declCls.getTypeParameters();
if (declTypes != null)
{
for (int j=0;j<declTypes.length;j++)
{
boolean foundTypeForTypeVariable = false;
if (declTypes[j].getName().equals(fieldTypeVar.getName()) && cls.getGenericSuperclass() instanceof ParameterizedType)
{
ParameterizedType genSuperclsType = (ParameterizedType) cls.getGenericSuperclass();
Type[] paramTypeArgs = genSuperclsType.getActualTypeArguments();
if (paramTypeArgs != null && paramTypeArgs.length > j && paramTypeArgs[j] instanceof Class)
{
NucleusLogger.METADATA.debug("Class=" + cls.getName() + " field=" + theclsFields[i].getName() +
" declared to be " + fieldTypeVar + ", namely TypeVariable(" + j + ") of " + declCls.getName() + " so using " + paramTypeArgs[j]);
String memberName = declCls.getName() + "." + theclsFields[i].getName();
if (!memberNames.contains(memberName))
{
if (hasProperties && api.equalsIgnoreCase("JPA"))
{
// Do nothing, since we will have a property
}
else
{
// No member of this name - add a default FieldMetaData for this field with the type set to what we need
NucleusLogger.METADATA.debug(Localiser.msg("044060", fullName, memberName));
AbstractMemberMetaData overriddenMmd = getMemberBeingOverridden(theclsFields[i].getName());
// Merge the overridden member with the limited info specified in this override
AbstractMemberMetaData mmd = new FieldMetaData(this, memberName);
// Note that if we override a single PK field we will have objectIdClass=ObjectId in the generics superclass, and still ObjectId here
// We have to keep to continue like this since the superclass will have been enhanced to have ObjectId in its bytecode contract.
mergeMemberMetaDataForOverrideOfType((Class) paramTypeArgs[j], mmd, overriddenMmd);
members.add(mmd);
memberNames.add(mmd.getName());
Collections.sort(members);
}
foundTypeForTypeVariable = true;
}
else
{
// TODO Cater for the user overriding it
}
}
}
if (!foundTypeForTypeVariable)
{
// Try bounds of declType
Type[] boundTypes = declTypes[j].getBounds();
// TODO Maybe should use just the declTypes for this specific class?
if (boundTypes != null && boundTypes.length == 1 && boundTypes[0] instanceof Class)
{
// User has class declaration like "public class MyClass<T extends SomeType>" so take SomeType
// TODO What if a superclass has already resolved the type? Do like with properties above?
NucleusLogger.METADATA.debug("Class=" + cls.getName() + " field=" + theclsFields[i].getName() +
" declared to be " + fieldTypeVar + ", namely TypeVariable(" + j + ") with bound, so using bound of " + boundTypes[0]);
String fieldName = declCls.getName() + "." + theclsFields[i].getName();
if (!memberNames.contains(fieldName))
After Change
if (!memberNames.contains(fieldName))
{
// Field defined as generic but not found a meta-data definition, so use boundTypes to add override meta-data with the correct type
NucleusLogger.METADATA.debug(Localiser.msg("044060", fullName, fieldNameFull));
// TODO Use MetaDataMerger to merge with superclass
AbstractMemberMetaData mmd = new FieldMetaData(this, fieldNameFull);